import SoundManager, { ClipPlayingInfo } from "./sound_manager";
import { Subject, SubjectComponent } from "./subject";

export class Sound2D extends Subject {
    cpInfo: ClipPlayingInfo = null;
    node: cc.Node = null;

    range = 0; //最远像素
    damping = 0.5; //衰减（暂无用）
    clipName = "";
    static Play(node: cc.Node, nameOrClip: string | cc.AudioClip, range = 750, damping = 0.5) {
        if (!cc.isValid(this.listenerIns)) {
            return;
        }
        let disToListener = node.convertToWorldSpaceAR(cc.Vec2.ZERO).sub(Sound2D.listenerIns.node.convertToWorldSpaceAR(cc.Vec2.ZERO)).len();
        if (disToListener > range) {
            return;
        }
        let sound = new Sound2D(node, nameOrClip, range, damping);
        Sound2D.listenerIns.addSound(sound);
        return sound;
    }
    constructor(node: cc.Node, name, range, damping) {
        super();
        this.node = node;
        this.clipName = name;
        this.range = range;
        this.damping = damping;
    }
    isNodeValid() {
        return cc.isValid(this.node);
    }
    onEnd() {
        this.cpInfo.onEnd(null);
        this.cpInfo = null;
        this.node = null;
        this.emit("end", this);
    }
    calcDisVolume() {
        if (!cc.isValid(Sound2D.listenerIns)) {
            return 0;
        }
        let disToListener = this.node.convertToWorldSpaceAR(cc.Vec2.ZERO).sub(Sound2D.listenerIns.node.convertToWorldSpaceAR(cc.Vec2.ZERO)).len();
        let pc = (this.range - disToListener) / this.range;

        return pc;
    }
    updateVolume() {
        this.cpInfo.volume = this.calcDisVolume();
    }
    play() {
        this.cpInfo = SoundManager.ins.playClip(this.clipName, false, this.calcDisVolume());
        if (this.cpInfo) {
            this.cpInfo.onEnd(this.onEnd.bind(this));
        }
        else {
            console.error("Sound2D::play, error: 没有找到", this.clipName);
        }
    }
    stop() {
        this.cpInfo.stop();
    }

    static listenerIns: Sound2DListener = null;
};



const { ccclass, property } = cc._decorator;
@ccclass
export default class Sound2DListener extends SubjectComponent {
    soundList: Sound2D[] = [];
    protected onEnable(): void {
        if (cc.isValid(Sound2D.listenerIns)) {
            console.warn("Sound2DListener 多个");
            // return;
        }
        Sound2D.listenerIns = this;
    }
    protected onDisable(): void {
        if (Sound2D.listenerIns === this) {
            this.stopAll();
            Sound2D.listenerIns = null;
        }
    }
    stopAll() {
        this.soundList.forEach(cpInfo => {
            cpInfo.stop();
        });
        this.soundList = [];
    }
    addSound(sound: Sound2D) {
        this.soundList.push(sound);
        sound.on("end", this.onSoundEnd, this);
        sound.play();
    }
    onSoundEnd(sound: Sound2D) {
        if (!this.isValid) {
            return;
        }
        let ind = this.soundList.findIndex(ele => ele === sound);
        if (ind !== -1) {
            this.soundList.splice(ind, 1);
        }
    }
    protected lateUpdate(dt: number): void {
        for (let i = 0; i < this.soundList.length;) {
            let sound = this.soundList[i];
            if (!sound.isNodeValid()) {
                this.soundList.splice(i, 1);
            }
            else {
                sound.updateVolume();
                i++;
            }

        }
    }
};